home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 18 Cube Mapping / CubeMap / CubeMapApp.cpp < prev    next >
C/C++ Source or Header  |  2016-03-02  |  44KB  |  1,152 lines

  1. //***************************************************************************************
  2. // CubeMapApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "../../Common/Camera.h"
  10. #include "FrameResource.h"
  11.  
  12. using Microsoft::WRL::ComPtr;
  13. using namespace DirectX;
  14. using namespace DirectX::PackedVector;
  15.  
  16. #pragma comment(lib, "d3dcompiler.lib")
  17. #pragma comment(lib, "D3D12.lib")
  18.  
  19. const int gNumFrameResources = 3;
  20.  
  21. // Lightweight structure stores parameters to draw a shape.  This will
  22. // vary from app-to-app.
  23. struct RenderItem
  24. {
  25.     RenderItem() = default;
  26.     RenderItem(const RenderItem& rhs) = delete;
  27.  
  28.     // World matrix of the shape that describes the object's local space
  29.     // relative to the world space, which defines the position, orientation,
  30.     // and scale of the object in the world.
  31.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  32.  
  33.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  34.  
  35.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  36.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  37.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  38.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  39.     int NumFramesDirty = gNumFrameResources;
  40.  
  41.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  42.     UINT ObjCBIndex = -1;
  43.  
  44.     Material* Mat = nullptr;
  45.     MeshGeometry* Geo = nullptr;
  46.  
  47.     // Primitive topology.
  48.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  49.  
  50.     // DrawIndexedInstanced parameters.
  51.     UINT IndexCount = 0;
  52.     UINT StartIndexLocation = 0;
  53.     int BaseVertexLocation = 0;
  54. };
  55.  
  56. enum class RenderLayer : int
  57. {
  58.     Opaque = 0,
  59.     Sky,
  60.     Count
  61. };
  62.  
  63. class CubeMapApp : public D3DApp
  64. {
  65. public:
  66.     CubeMapApp(HINSTANCE hInstance);
  67.     CubeMapApp(const CubeMapApp& rhs) = delete;
  68.     CubeMapApp& operator=(const CubeMapApp& rhs) = delete;
  69.     ~CubeMapApp();
  70.  
  71.     virtual bool Initialize()override;
  72.  
  73. private:
  74.     virtual void OnResize()override;
  75.     virtual void Update(const GameTimer& gt)override;
  76.     virtual void Draw(const GameTimer& gt)override;
  77.  
  78.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  79.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  80.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  81.  
  82.     void OnKeyboardInput(const GameTimer& gt);
  83.     void AnimateMaterials(const GameTimer& gt);
  84.     void UpdateObjectCBs(const GameTimer& gt);
  85.     void UpdateMaterialBuffer(const GameTimer& gt);
  86.     void UpdateMainPassCB(const GameTimer& gt);
  87.  
  88.     void LoadTextures();
  89.     void BuildRootSignature();
  90.     void BuildDescriptorHeaps();
  91.     void BuildShadersAndInputLayout();
  92.     void BuildShapeGeometry();
  93.     void BuildSkullGeometry();
  94.     void BuildPSOs();
  95.     void BuildFrameResources();
  96.     void BuildMaterials();
  97.     void BuildRenderItems();
  98.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  99.  
  100.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
  101.  
  102. private:
  103.  
  104.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  105.     FrameResource* mCurrFrameResource = nullptr;
  106.     int mCurrFrameResourceIndex = 0;
  107.  
  108.     UINT mCbvSrvDescriptorSize = 0;
  109.  
  110.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  111.  
  112.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  113.  
  114.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  115.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  116.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  117.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  118.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  119.  
  120.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  121.  
  122.     // List of all the render items.
  123.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  124.  
  125.     // Render items divided by PSO.
  126.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  127.  
  128.     UINT mSkyTexHeapIndex = 0;
  129.  
  130.     PassConstants mMainPassCB;
  131.  
  132.     Camera mCamera;
  133.  
  134.     POINT mLastMousePos;
  135. };
  136.  
  137. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  138.     PSTR cmdLine, int showCmd)
  139. {
  140.     // Enable run-time memory check for debug builds.
  141. #if defined(DEBUG) | defined(_DEBUG)
  142.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  143. #endif
  144.  
  145.     try
  146.     {
  147.         CubeMapApp theApp(hInstance);
  148.         if(!theApp.Initialize())
  149.             return 0;
  150.  
  151.         return theApp.Run();
  152.     }
  153.     catch(DxException& e)
  154.     {
  155.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  156.         return 0;
  157.     }
  158. }
  159.  
  160. CubeMapApp::CubeMapApp(HINSTANCE hInstance)
  161.     : D3DApp(hInstance)
  162. {
  163. }
  164.  
  165. CubeMapApp::~CubeMapApp()
  166. {
  167. }
  168.  
  169. bool CubeMapApp::Initialize()
  170. {
  171.     if(!D3DApp::Initialize())
  172.         return false;
  173.  
  174.     // Reset the command list to prep for initialization commands.
  175.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  176.  
  177.     // Get the increment size of a descriptor in this heap type.  This is hardware specific, 
  178.     // so we have to query this information.
  179.     mCbvSrvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  180.  
  181.     mCamera.SetPosition(0.0f, 2.0f, -15.0f);
  182.  
  183.     LoadTextures();
  184.     BuildRootSignature();
  185.     BuildDescriptorHeaps();
  186.     BuildShadersAndInputLayout();
  187.     BuildShapeGeometry();
  188.     BuildSkullGeometry();
  189.     BuildMaterials();
  190.     BuildRenderItems();
  191.     BuildFrameResources();
  192.     BuildPSOs();
  193.  
  194.     // Execute the initialization commands.
  195.     ThrowIfFailed(mCommandList->Close());
  196.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  197.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  198.  
  199.     // Wait until initialization is complete.
  200.     FlushCommandQueue();
  201.  
  202.     return true;
  203. }
  204.  
  205. void CubeMapApp::OnResize()
  206. {
  207.     D3DApp::OnResize();
  208.  
  209.     mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  210. }
  211.  
  212. void CubeMapApp::Update(const GameTimer& gt)
  213. {
  214.     OnKeyboardInput(gt);
  215.  
  216.     // Cycle through the circular frame resource array.
  217.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  218.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  219.  
  220.     // Has the GPU finished processing the commands of the current frame resource?
  221.     // If not, wait until the GPU has completed commands up to this fence point.
  222.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  223.     {
  224.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  225.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  226.         WaitForSingleObject(eventHandle, INFINITE);
  227.         CloseHandle(eventHandle);
  228.     }
  229.  
  230.     AnimateMaterials(gt);
  231.     UpdateObjectCBs(gt);
  232.     UpdateMaterialBuffer(gt);
  233.     UpdateMainPassCB(gt);
  234. }
  235.  
  236. void CubeMapApp::Draw(const GameTimer& gt)
  237. {
  238.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  239.  
  240.     // Reuse the memory associated with command recording.
  241.     // We can only reset when the associated command lists have finished execution on the GPU.
  242.     ThrowIfFailed(cmdListAlloc->Reset());
  243.  
  244.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  245.     // Reusing the command list reuses memory.
  246.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  247.  
  248.     mCommandList->RSSetViewports(1, &mScreenViewport);
  249.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  250.  
  251.     // Indicate a state transition on the resource usage.
  252.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  253.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  254.  
  255.     // Clear the back buffer and depth buffer.
  256.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  257.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  258.  
  259.     // Specify the buffers we are going to render to.
  260.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  261.  
  262.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  263.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  264.  
  265.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  266.  
  267.     auto passCB = mCurrFrameResource->PassCB->Resource();
  268.     mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());
  269.  
  270.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  271.     // set as a root descriptor.
  272.     auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  273.     mCommandList->SetGraphicsRootShaderResourceView(2, matBuffer->GetGPUVirtualAddress());
  274.  
  275.     // Bind the sky cube map.  For our demos, we just use one "world" cube map representing the environment
  276.     // from far away, so all objects will use the same cube map and we only need to set it once per-frame.  
  277.     // If we wanted to use "local" cube maps, we would have to change them per-object, or dynamically
  278.     // index into an array of cube maps.
  279.  
  280.     CD3DX12_GPU_DESCRIPTOR_HANDLE skyTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  281.     skyTexDescriptor.Offset(mSkyTexHeapIndex, mCbvSrvDescriptorSize);
  282.     mCommandList->SetGraphicsRootDescriptorTable(3, skyTexDescriptor);
  283.  
  284.     // Bind all the textures used in this scene.  Observe
  285.     // that we only have to specify the first descriptor in the table.  
  286.     // The root signature knows how many descriptors are expected in the table.
  287.     mCommandList->SetGraphicsRootDescriptorTable(4, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  288.  
  289.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  290.  
  291.     mCommandList->SetPipelineState(mPSOs["sky"].Get());
  292.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
  293.  
  294.     // Indicate a state transition on the resource usage.
  295.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  296.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  297.  
  298.     // Done recording commands.
  299.     ThrowIfFailed(mCommandList->Close());
  300.  
  301.     // Add the command list to the queue for execution.
  302.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  303.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  304.  
  305.     // Swap the back and front buffers
  306.     ThrowIfFailed(mSwapChain->Present(0, 0));
  307.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  308.  
  309.     // Advance the fence value to mark commands up to this fence point.
  310.     mCurrFrameResource->Fence = ++mCurrentFence;
  311.  
  312.     // Add an instruction to the command queue to set a new fence point. 
  313.     // Because we are on the GPU timeline, the new fence point won't be 
  314.     // set until the GPU finishes processing all the commands prior to this Signal().
  315.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  316. }
  317.  
  318. void CubeMapApp::OnMouseDown(WPARAM btnState, int x, int y)
  319. {
  320.     mLastMousePos.x = x;
  321.     mLastMousePos.y = y;
  322.  
  323.     SetCapture(mhMainWnd);
  324. }
  325.  
  326. void CubeMapApp::OnMouseUp(WPARAM btnState, int x, int y)
  327. {
  328.     ReleaseCapture();
  329. }
  330.  
  331. void CubeMapApp::OnMouseMove(WPARAM btnState, int x, int y)
  332. {
  333.     if((btnState & MK_LBUTTON) != 0)
  334.     {
  335.         // Make each pixel correspond to a quarter of a degree.
  336.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  337.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  338.  
  339.         mCamera.Pitch(dy);
  340.         mCamera.RotateY(dx);
  341.     }
  342.  
  343.     mLastMousePos.x = x;
  344.     mLastMousePos.y = y;
  345. }
  346.  
  347. void CubeMapApp::OnKeyboardInput(const GameTimer& gt)
  348. {
  349.     const float dt = gt.DeltaTime();
  350.  
  351.     if(GetAsyncKeyState('W') & 0x8000)
  352.         mCamera.Walk(10.0f*dt);
  353.  
  354.     if(GetAsyncKeyState('S') & 0x8000)
  355.         mCamera.Walk(-10.0f*dt);
  356.  
  357.     if(GetAsyncKeyState('A') & 0x8000)
  358.         mCamera.Strafe(-10.0f*dt);
  359.  
  360.     if(GetAsyncKeyState('D') & 0x8000)
  361.         mCamera.Strafe(10.0f*dt);
  362.  
  363.     mCamera.UpdateViewMatrix();
  364. }
  365.  
  366. void CubeMapApp::AnimateMaterials(const GameTimer& gt)
  367. {
  368.     
  369. }
  370.  
  371. void CubeMapApp::UpdateObjectCBs(const GameTimer& gt)
  372. {
  373.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  374.     for(auto& e : mAllRitems)
  375.     {
  376.         // Only update the cbuffer data if the constants have changed.  
  377.         // This needs to be tracked per frame resource.
  378.         if(e->NumFramesDirty > 0)
  379.         {
  380.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  381.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  382.  
  383.             ObjectConstants objConstants;
  384.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  385.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  386.             objConstants.MaterialIndex = e->Mat->MatCBIndex;
  387.  
  388.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  389.  
  390.             // Next FrameResource need to be updated too.
  391.             e->NumFramesDirty--;
  392.         }
  393.     }
  394. }
  395.  
  396. void CubeMapApp::UpdateMaterialBuffer(const GameTimer& gt)
  397. {
  398.     auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
  399.     for(auto& e : mMaterials)
  400.     {
  401.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  402.         // data changes, it needs to be updated for each FrameResource.
  403.         Material* mat = e.second.get();
  404.         if(mat->NumFramesDirty > 0)
  405.         {
  406.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  407.  
  408.             MaterialData matData;
  409.             matData.DiffuseAlbedo = mat->DiffuseAlbedo;
  410.             matData.FresnelR0 = mat->FresnelR0;
  411.             matData.Roughness = mat->Roughness;
  412.             XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
  413.             matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
  414.  
  415.             currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
  416.  
  417.             // Next FrameResource need to be updated too.
  418.             mat->NumFramesDirty--;
  419.         }
  420.     }
  421. }
  422.  
  423. void CubeMapApp::UpdateMainPassCB(const GameTimer& gt)
  424. {
  425.     XMMATRIX view = mCamera.GetView();
  426.     XMMATRIX proj = mCamera.GetProj();
  427.  
  428.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  429.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  430.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  431.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  432.  
  433.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  434.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  435.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  436.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  437.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  438.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  439.     mMainPassCB.EyePosW = mCamera.GetPosition3f();
  440.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  441.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  442.     mMainPassCB.NearZ = 1.0f;
  443.     mMainPassCB.FarZ = 1000.0f;
  444.     mMainPassCB.TotalTime = gt.TotalTime();
  445.     mMainPassCB.DeltaTime = gt.DeltaTime();
  446.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  447.     mMainPassCB.Lights[0].Direction = { 0.57735f, -0.57735f, 0.57735f };
  448.     mMainPassCB.Lights[0].Strength = { 0.6f, 0.6f, 0.6f };
  449.     mMainPassCB.Lights[1].Direction = { -0.57735f, -0.57735f, 0.57735f };
  450.     mMainPassCB.Lights[1].Strength = { 0.3f, 0.3f, 0.3f };
  451.     mMainPassCB.Lights[2].Direction = { 0.0f, -0.707f, -0.707f };
  452.     mMainPassCB.Lights[2].Strength = { 0.15f, 0.15f, 0.15f };
  453.  
  454.     auto currPassCB = mCurrFrameResource->PassCB.get();
  455.     currPassCB->CopyData(0, mMainPassCB);
  456. }
  457.  
  458. void CubeMapApp::LoadTextures()
  459. {
  460.     std::vector<std::string> texNames =
  461.     {
  462.         "bricksDiffuseMap",
  463.         "tileDiffuseMap",
  464.         "defaultDiffuseMap",
  465.         "skyCubeMap"
  466.     };
  467.  
  468.     std::vector<std::wstring> texFilenames =
  469.     {
  470.         L"../../Textures/bricks2.dds",
  471.         L"../../Textures/tile.dds",
  472.         L"../../Textures/white1x1.dds",
  473.         L"../../Textures/grasscube1024.dds"
  474.     };
  475.  
  476.     for (int i = 0; i < (int)texNames.size(); ++i)
  477.     {
  478.         auto texMap = std::make_unique<Texture>();
  479.         texMap->Name = texNames[i];
  480.         texMap->Filename = texFilenames[i];
  481.         ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  482.             mCommandList.Get(), texMap->Filename.c_str(),
  483.             texMap->Resource, texMap->UploadHeap));
  484.  
  485.         mTextures[texMap->Name] = std::move(texMap);
  486.     }
  487. }
  488.  
  489. void CubeMapApp::BuildRootSignature()
  490. {
  491.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  492.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0, 0);
  493.  
  494.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  495.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 5, 1, 0);
  496.  
  497.     // Root parameter can be a table, root descriptor or root constants.
  498.     CD3DX12_ROOT_PARAMETER slotRootParameter[5];
  499.  
  500.     // Perfomance TIP: Order from most frequent to least frequent.
  501.     slotRootParameter[0].InitAsConstantBufferView(0);
  502.     slotRootParameter[1].InitAsConstantBufferView(1);
  503.     slotRootParameter[2].InitAsShaderResourceView(0, 1);
  504.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  505.     slotRootParameter[4].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  506.  
  507.  
  508.     auto staticSamplers = GetStaticSamplers();
  509.  
  510.     // A root signature is an array of root parameters.
  511.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5, slotRootParameter,
  512.         (UINT)staticSamplers.size(), staticSamplers.data(),
  513.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  514.  
  515.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  516.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  517.     ComPtr<ID3DBlob> errorBlob = nullptr;
  518.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  519.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  520.  
  521.     if(errorBlob != nullptr)
  522.     {
  523.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  524.     }
  525.     ThrowIfFailed(hr);
  526.  
  527.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  528.         0,
  529.         serializedRootSig->GetBufferPointer(),
  530.         serializedRootSig->GetBufferSize(),
  531.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  532. }
  533.  
  534. void CubeMapApp::BuildDescriptorHeaps()
  535. {
  536.     //
  537.     // Create the SRV heap.
  538.     //
  539.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  540.     srvHeapDesc.NumDescriptors = 5;
  541.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  542.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  543.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  544.  
  545.     //
  546.     // Fill out the heap with actual descriptors.
  547.     //
  548.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  549.  
  550.     auto bricksTex = mTextures["bricksDiffuseMap"]->Resource;
  551.     auto tileTex = mTextures["tileDiffuseMap"]->Resource;
  552.     auto whiteTex = mTextures["defaultDiffuseMap"]->Resource;
  553.     auto skyTex = mTextures["skyCubeMap"]->Resource;
  554.  
  555.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  556.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  557.     srvDesc.Format = bricksTex->GetDesc().Format;
  558.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  559.     srvDesc.Texture2D.MostDetailedMip = 0;
  560.     srvDesc.Texture2D.MipLevels = bricksTex->GetDesc().MipLevels;
  561.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  562.     md3dDevice->CreateShaderResourceView(bricksTex.Get(), &srvDesc, hDescriptor);
  563.  
  564.     // next descriptor
  565.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  566.  
  567.     srvDesc.Format = tileTex->GetDesc().Format;
  568.     srvDesc.Texture2D.MipLevels = tileTex->GetDesc().MipLevels;
  569.     md3dDevice->CreateShaderResourceView(tileTex.Get(), &srvDesc, hDescriptor);
  570.  
  571.     // next descriptor
  572.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  573.  
  574.     srvDesc.Format = whiteTex->GetDesc().Format;
  575.     srvDesc.Texture2D.MipLevels = whiteTex->GetDesc().MipLevels;
  576.     md3dDevice->CreateShaderResourceView(whiteTex.Get(), &srvDesc, hDescriptor);
  577.  
  578.     // next descriptor
  579.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  580.  
  581.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
  582.     srvDesc.TextureCube.MostDetailedMip = 0;
  583.     srvDesc.TextureCube.MipLevels = skyTex->GetDesc().MipLevels;
  584.     srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
  585.     srvDesc.Format = skyTex->GetDesc().Format;
  586.     md3dDevice->CreateShaderResourceView(skyTex.Get(), &srvDesc, hDescriptor);
  587.     
  588.     mSkyTexHeapIndex = 3;
  589. }
  590.  
  591. void CubeMapApp::BuildShadersAndInputLayout()
  592. {
  593.     const D3D_SHADER_MACRO alphaTestDefines[] =
  594.     {
  595.         "ALPHA_TEST", "1",
  596.         NULL, NULL
  597.     };
  598.  
  599.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
  600.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
  601.     
  602.     mShaders["skyVS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "VS", "vs_5_1");
  603.     mShaders["skyPS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "PS", "ps_5_1");
  604.  
  605.     mInputLayout =
  606.     {
  607.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  608.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  609.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  610.     };
  611. }
  612.  
  613. void CubeMapApp::BuildShapeGeometry()
  614. {
  615.     GeometryGenerator geoGen;
  616.     GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
  617.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  618.     GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  619.     GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  620.  
  621.     //
  622.     // We are concatenating all the geometry into one big vertex/index buffer.  So
  623.     // define the regions in the buffer each submesh covers.
  624.     //
  625.  
  626.     // Cache the vertex offsets to each object in the concatenated vertex buffer.
  627.     UINT boxVertexOffset = 0;
  628.     UINT gridVertexOffset = (UINT)box.Vertices.size();
  629.     UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  630.     UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  631.  
  632.     // Cache the starting index for each object in the concatenated index buffer.
  633.     UINT boxIndexOffset = 0;
  634.     UINT gridIndexOffset = (UINT)box.Indices32.size();
  635.     UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  636.     UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  637.  
  638.     SubmeshGeometry boxSubmesh;
  639.     boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  640.     boxSubmesh.StartIndexLocation = boxIndexOffset;
  641.     boxSubmesh.BaseVertexLocation = boxVertexOffset;
  642.  
  643.     SubmeshGeometry gridSubmesh;
  644.     gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  645.     gridSubmesh.StartIndexLocation = gridIndexOffset;
  646.     gridSubmesh.BaseVertexLocation = gridVertexOffset;
  647.  
  648.     SubmeshGeometry sphereSubmesh;
  649.     sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  650.     sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  651.     sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  652.  
  653.     SubmeshGeometry cylinderSubmesh;
  654.     cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  655.     cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  656.     cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  657.  
  658.     //
  659.     // Extract the vertex elements we are interested in and pack the
  660.     // vertices of all the meshes into one vertex buffer.
  661.     //
  662.  
  663.     auto totalVertexCount =
  664.         box.Vertices.size() +
  665.         grid.Vertices.size() +
  666.         sphere.Vertices.size() +
  667.         cylinder.Vertices.size();
  668.  
  669.     std::vector<Vertex> vertices(totalVertexCount);
  670.  
  671.     UINT k = 0;
  672.     for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  673.     {
  674.         vertices[k].Pos = box.Vertices[i].Position;
  675.         vertices[k].Normal = box.Vertices[i].Normal;
  676.         vertices[k].TexC = box.Vertices[i].TexC;
  677.     }
  678.  
  679.     for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  680.     {
  681.         vertices[k].Pos = grid.Vertices[i].Position;
  682.         vertices[k].Normal = grid.Vertices[i].Normal;
  683.         vertices[k].TexC = grid.Vertices[i].TexC;
  684.     }
  685.  
  686.     for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  687.     {
  688.         vertices[k].Pos = sphere.Vertices[i].Position;
  689.         vertices[k].Normal = sphere.Vertices[i].Normal;
  690.         vertices[k].TexC = sphere.Vertices[i].TexC;
  691.     }
  692.  
  693.     for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  694.     {
  695.         vertices[k].Pos = cylinder.Vertices[i].Position;
  696.         vertices[k].Normal = cylinder.Vertices[i].Normal;
  697.         vertices[k].TexC = cylinder.Vertices[i].TexC;
  698.     }
  699.  
  700.     std::vector<std::uint16_t> indices;
  701.     indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  702.     indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  703.     indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  704.     indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  705.  
  706.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  707.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  708.  
  709.     auto geo = std::make_unique<MeshGeometry>();
  710.     geo->Name = "shapeGeo";
  711.  
  712.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  713.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  714.  
  715.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  716.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  717.  
  718.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  719.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  720.  
  721.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  722.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  723.  
  724.     geo->VertexByteStride = sizeof(Vertex);
  725.     geo->VertexBufferByteSize = vbByteSize;
  726.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  727.     geo->IndexBufferByteSize = ibByteSize;
  728.  
  729.     geo->DrawArgs["box"] = boxSubmesh;
  730.     geo->DrawArgs["grid"] = gridSubmesh;
  731.     geo->DrawArgs["sphere"] = sphereSubmesh;
  732.     geo->DrawArgs["cylinder"] = cylinderSubmesh;
  733.  
  734.     mGeometries[geo->Name] = std::move(geo);
  735. }
  736.  
  737. void CubeMapApp::BuildSkullGeometry()
  738. {
  739.     std::ifstream fin("Models/skull.txt");
  740.  
  741.     if (!fin)
  742.     {
  743.         MessageBox(0, L"Models/skull.txt not found.", 0, 0);
  744.         return;
  745.     }
  746.  
  747.     UINT vcount = 0;
  748.     UINT tcount = 0;
  749.     std::string ignore;
  750.  
  751.     fin >> ignore >> vcount;
  752.     fin >> ignore >> tcount;
  753.     fin >> ignore >> ignore >> ignore >> ignore;
  754.  
  755.     XMFLOAT3 vMinf3(+MathHelper::Infinity, +MathHelper::Infinity, +MathHelper::Infinity);
  756.     XMFLOAT3 vMaxf3(-MathHelper::Infinity, -MathHelper::Infinity, -MathHelper::Infinity);
  757.  
  758.     XMVECTOR vMin = XMLoadFloat3(&vMinf3);
  759.     XMVECTOR vMax = XMLoadFloat3(&vMaxf3);
  760.  
  761.     std::vector<Vertex> vertices(vcount);
  762.     for (UINT i = 0; i < vcount; ++i)
  763.     {
  764.         fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
  765.         fin >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z;
  766.  
  767.         vertices[i].TexC = { 0.0f, 0.0f };
  768.  
  769.         XMVECTOR P = XMLoadFloat3(&vertices[i].Pos);
  770.  
  771.         vMin = XMVectorMin(vMin, P);
  772.         vMax = XMVectorMax(vMax, P);
  773.     }
  774.  
  775.     BoundingBox bounds;
  776.     XMStoreFloat3(&bounds.Center, 0.5f*(vMin + vMax));
  777.     XMStoreFloat3(&bounds.Extents, 0.5f*(vMax - vMin));
  778.  
  779.     fin >> ignore;
  780.     fin >> ignore;
  781.     fin >> ignore;
  782.  
  783.     std::vector<std::int32_t> indices(3 * tcount);
  784.     for (UINT i = 0; i < tcount; ++i)
  785.     {
  786.         fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2];
  787.     }
  788.  
  789.     fin.close();
  790.  
  791.     //
  792.     // Pack the indices of all the meshes into one index buffer.
  793.     //
  794.  
  795.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  796.  
  797.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::int32_t);
  798.  
  799.     auto geo = std::make_unique<MeshGeometry>();
  800.     geo->Name = "skullGeo";
  801.  
  802.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  803.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  804.  
  805.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  806.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  807.  
  808.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  809.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  810.  
  811.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  812.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  813.  
  814.     geo->VertexByteStride = sizeof(Vertex);
  815.     geo->VertexBufferByteSize = vbByteSize;
  816.     geo->IndexFormat = DXGI_FORMAT_R32_UINT;
  817.     geo->IndexBufferByteSize = ibByteSize;
  818.  
  819.     SubmeshGeometry submesh;
  820.     submesh.IndexCount = (UINT)indices.size();
  821.     submesh.StartIndexLocation = 0;
  822.     submesh.BaseVertexLocation = 0;
  823.     submesh.Bounds = bounds;
  824.  
  825.     geo->DrawArgs["skull"] = submesh;
  826.  
  827.     mGeometries[geo->Name] = std::move(geo);
  828. }
  829.  
  830. void CubeMapApp::BuildPSOs()
  831. {
  832.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  833.  
  834.     //
  835.     // PSO for opaque objects.
  836.     //
  837.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  838.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  839.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  840.     opaquePsoDesc.VS = 
  841.     { 
  842.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  843.         mShaders["standardVS"]->GetBufferSize()
  844.     };
  845.     opaquePsoDesc.PS = 
  846.     { 
  847.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  848.         mShaders["opaquePS"]->GetBufferSize()
  849.     };
  850.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  851.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  852.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  853.     opaquePsoDesc.SampleMask = UINT_MAX;
  854.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  855.     opaquePsoDesc.NumRenderTargets = 1;
  856.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  857.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  858.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  859.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  860.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  861.  
  862.     //
  863.     // PSO for sky.
  864.     //
  865.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skyPsoDesc = opaquePsoDesc;
  866.  
  867.     // The camera is inside the sky sphere, so just turn off culling.
  868.     skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
  869.  
  870.     // Make sure the depth function is LESS_EQUAL and not just LESS.  
  871.     // Otherwise, the normalized depth values at z = 1 (NDC) will 
  872.     // fail the depth test if the depth buffer was cleared to 1.
  873.     skyPsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
  874.     skyPsoDesc.pRootSignature = mRootSignature.Get();
  875.     skyPsoDesc.VS =
  876.     {
  877.         reinterpret_cast<BYTE*>(mShaders["skyVS"]->GetBufferPointer()),
  878.         mShaders["skyVS"]->GetBufferSize()
  879.     };
  880.     skyPsoDesc.PS =
  881.     {
  882.         reinterpret_cast<BYTE*>(mShaders["skyPS"]->GetBufferPointer()),
  883.         mShaders["skyPS"]->GetBufferSize()
  884.     };
  885.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skyPsoDesc, IID_PPV_ARGS(&mPSOs["sky"])));
  886.  
  887. }
  888.  
  889. void CubeMapApp::BuildFrameResources()
  890. {
  891.     for(int i = 0; i < gNumFrameResources; ++i)
  892.     {
  893.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  894.             1, (UINT)mAllRitems.size(), (UINT)mMaterials.size()));
  895.     }
  896. }
  897.  
  898. void CubeMapApp::BuildMaterials()
  899. {
  900.     auto bricks0 = std::make_unique<Material>();
  901.     bricks0->Name = "bricks0";
  902.     bricks0->MatCBIndex = 0;
  903.     bricks0->DiffuseSrvHeapIndex = 0;
  904.     bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  905.     bricks0->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  906.     bricks0->Roughness = 0.3f;
  907.  
  908.     auto tile0 = std::make_unique<Material>();
  909.     tile0->Name = "tile0";
  910.     tile0->MatCBIndex = 1;
  911.     tile0->DiffuseSrvHeapIndex = 1;
  912.     tile0->DiffuseAlbedo = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
  913.     tile0->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  914.     tile0->Roughness = 0.1f;
  915.  
  916.     auto mirror0 = std::make_unique<Material>();
  917.     mirror0->Name = "mirror0";
  918.     mirror0->MatCBIndex = 2;
  919.     mirror0->DiffuseSrvHeapIndex = 2;
  920.     mirror0->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.1f, 1.0f);
  921.     mirror0->FresnelR0 = XMFLOAT3(0.98f, 0.97f, 0.95f);
  922.     mirror0->Roughness = 0.1f;
  923.  
  924.     auto skullMat = std::make_unique<Material>();
  925.     skullMat->Name = "skullMat";
  926.     skullMat->MatCBIndex = 3;
  927.     skullMat->DiffuseSrvHeapIndex = 2;
  928.     skullMat->DiffuseAlbedo = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f);
  929.     skullMat->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  930.     skullMat->Roughness = 0.2f;
  931.  
  932.     auto sky = std::make_unique<Material>();
  933.     sky->Name = "sky";
  934.     sky->MatCBIndex = 4;
  935.     sky->DiffuseSrvHeapIndex = 3;
  936.     sky->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  937.     sky->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  938.     sky->Roughness = 1.0f;
  939.  
  940.     mMaterials["bricks0"] = std::move(bricks0);
  941.     mMaterials["tile0"] = std::move(tile0);
  942.     mMaterials["mirror0"] = std::move(mirror0);
  943.     mMaterials["skullMat"] = std::move(skullMat);
  944.     mMaterials["sky"] = std::move(sky);
  945. }
  946.  
  947. void CubeMapApp::BuildRenderItems()
  948. {
  949.     auto skyRitem = std::make_unique<RenderItem>();
  950.     XMStoreFloat4x4(&skyRitem->World, XMMatrixScaling(5000.0f, 5000.0f, 5000.0f));
  951.     skyRitem->TexTransform = MathHelper::Identity4x4();
  952.     skyRitem->ObjCBIndex = 0;
  953.     skyRitem->Mat = mMaterials["sky"].get();
  954.     skyRitem->Geo = mGeometries["shapeGeo"].get();
  955.     skyRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  956.     skyRitem->IndexCount = skyRitem->Geo->DrawArgs["sphere"].IndexCount;
  957.     skyRitem->StartIndexLocation = skyRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  958.     skyRitem->BaseVertexLocation = skyRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  959.  
  960.     mRitemLayer[(int)RenderLayer::Sky].push_back(skyRitem.get());
  961.     mAllRitems.push_back(std::move(skyRitem));
  962.  
  963.     auto boxRitem = std::make_unique<RenderItem>();
  964.     XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 1.0f, 2.0f)*XMMatrixTranslation(0.0f, 0.5f, 0.0f));
  965.     XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 1.0f, 1.0f));
  966.     boxRitem->ObjCBIndex = 1;
  967.     boxRitem->Mat = mMaterials["bricks0"].get();
  968.     boxRitem->Geo = mGeometries["shapeGeo"].get();
  969.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  970.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  971.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  972.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  973.  
  974.     mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
  975.     mAllRitems.push_back(std::move(boxRitem));
  976.  
  977.     auto skullRitem = std::make_unique<RenderItem>();
  978.     XMStoreFloat4x4(&skullRitem->World, XMMatrixScaling(0.4f, 0.4f, 0.4f)*XMMatrixTranslation(0.0f, 1.0f, 0.0f));
  979.     skullRitem->TexTransform = MathHelper::Identity4x4();
  980.     skullRitem->ObjCBIndex = 2;
  981.     skullRitem->Mat = mMaterials["skullMat"].get();
  982.     skullRitem->Geo = mGeometries["skullGeo"].get();
  983.     skullRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  984.     skullRitem->IndexCount = skullRitem->Geo->DrawArgs["skull"].IndexCount;
  985.     skullRitem->StartIndexLocation = skullRitem->Geo->DrawArgs["skull"].StartIndexLocation;
  986.     skullRitem->BaseVertexLocation = skullRitem->Geo->DrawArgs["skull"].BaseVertexLocation;
  987.  
  988.     mRitemLayer[(int)RenderLayer::Opaque].push_back(skullRitem.get());
  989.     mAllRitems.push_back(std::move(skullRitem));
  990.  
  991.     auto gridRitem = std::make_unique<RenderItem>();
  992.     gridRitem->World = MathHelper::Identity4x4();
  993.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
  994.     gridRitem->ObjCBIndex = 3;
  995.     gridRitem->Mat = mMaterials["tile0"].get();
  996.     gridRitem->Geo = mGeometries["shapeGeo"].get();
  997.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  998.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  999.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1000.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1001.  
  1002.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  1003.     mAllRitems.push_back(std::move(gridRitem));
  1004.  
  1005.     XMMATRIX brickTexTransform = XMMatrixScaling(1.5f, 2.0f, 1.0f);
  1006.     UINT objCBIndex = 4;
  1007.     for(int i = 0; i < 5; ++i)
  1008.     {
  1009.         auto leftCylRitem = std::make_unique<RenderItem>();
  1010.         auto rightCylRitem = std::make_unique<RenderItem>();
  1011.         auto leftSphereRitem = std::make_unique<RenderItem>();
  1012.         auto rightSphereRitem = std::make_unique<RenderItem>();
  1013.  
  1014.         XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
  1015.         XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
  1016.  
  1017.         XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
  1018.         XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
  1019.  
  1020.         XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  1021.         XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
  1022.         leftCylRitem->ObjCBIndex = objCBIndex++;
  1023.         leftCylRitem->Mat = mMaterials["bricks0"].get();
  1024.         leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  1025.         leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1026.         leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1027.         leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1028.         leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1029.  
  1030.         XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  1031.         XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
  1032.         rightCylRitem->ObjCBIndex = objCBIndex++;
  1033.         rightCylRitem->Mat = mMaterials["bricks0"].get();
  1034.         rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  1035.         rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1036.         rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1037.         rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1038.         rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1039.  
  1040.         XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  1041.         leftSphereRitem->TexTransform = MathHelper::Identity4x4();
  1042.         leftSphereRitem->ObjCBIndex = objCBIndex++;
  1043.         leftSphereRitem->Mat = mMaterials["mirror0"].get();
  1044.         leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1045.         leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1046.         leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1047.         leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1048.         leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1049.  
  1050.         XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  1051.         rightSphereRitem->TexTransform = MathHelper::Identity4x4();
  1052.         rightSphereRitem->ObjCBIndex = objCBIndex++;
  1053.         rightSphereRitem->Mat = mMaterials["mirror0"].get();
  1054.         rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1055.         rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1056.         rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1057.         rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1058.         rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1059.  
  1060.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftCylRitem.get());
  1061.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightCylRitem.get());
  1062.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftSphereRitem.get());
  1063.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightSphereRitem.get());
  1064.  
  1065.         mAllRitems.push_back(std::move(leftCylRitem));
  1066.         mAllRitems.push_back(std::move(rightCylRitem));
  1067.         mAllRitems.push_back(std::move(leftSphereRitem));
  1068.         mAllRitems.push_back(std::move(rightSphereRitem));
  1069.     }
  1070. }
  1071.  
  1072. void CubeMapApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  1073. {
  1074.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  1075.  
  1076.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  1077.  
  1078.     // For each render item...
  1079.     for(size_t i = 0; i < ritems.size(); ++i)
  1080.     {
  1081.         auto ri = ritems[i];
  1082.  
  1083.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  1084.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  1085.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  1086.  
  1087.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  1088.  
  1089.         cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
  1090.  
  1091.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  1092.     }
  1093. }
  1094.  
  1095. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> CubeMapApp::GetStaticSamplers()
  1096. {
  1097.     // Applications usually only need a handful of samplers.  So just define them all up front
  1098.     // and keep them available as part of the root signature.  
  1099.  
  1100.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  1101.         0, // shaderRegister
  1102.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1103.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1104.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1105.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1106.  
  1107.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  1108.         1, // shaderRegister
  1109.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1110.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1111.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1112.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1113.  
  1114.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  1115.         2, // shaderRegister
  1116.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1117.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1118.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1119.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1120.  
  1121.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  1122.         3, // shaderRegister
  1123.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1124.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1125.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1126.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1127.  
  1128.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  1129.         4, // shaderRegister
  1130.         D3D12_FILTER_ANISOTROPIC, // filter
  1131.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1132.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1133.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1134.         0.0f,                             // mipLODBias
  1135.         8);                               // maxAnisotropy
  1136.  
  1137.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1138.         5, // shaderRegister
  1139.         D3D12_FILTER_ANISOTROPIC, // filter
  1140.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1141.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1142.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1143.         0.0f,                              // mipLODBias
  1144.         8);                                // maxAnisotropy
  1145.  
  1146.     return { 
  1147.         pointWrap, pointClamp,
  1148.         linearWrap, linearClamp, 
  1149.         anisotropicWrap, anisotropicClamp };
  1150. }
  1151.  
  1152.